package com.sharemarking.wa.platform.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.sharemarking.wa.common.ResponseParams;
import com.sharemarking.wa.common.SysHttpStatus;
import com.sharemarking.wa.common.entity.*;
import com.sharemarking.wa.common.eum.CacheNameEum;
import com.sharemarking.wa.common.eum.VailCodeTypeEum;
import com.sharemarking.wa.common.exception.AuthException;
import com.sharemarking.wa.common.exception.RequestException;
import com.sharemarking.wa.platform.dto.AreaDto;
import com.sharemarking.wa.platform.dto.VersionDto;
import com.sharemarking.wa.platform.dto.cms.CmsPostInfoDto;
import com.sharemarking.wa.platform.dto.company.CompanyDto;
import com.sharemarking.wa.platform.dto.company.CompanyInfoDto;
import com.sharemarking.wa.platform.dto.driverVerify.DriverVerifyDto;
import com.sharemarking.wa.platform.mapper.*;
import com.sharemarking.wa.platform.service.impl.Md5ServiceImpl;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.*;
import java.util.List;

/**
 * @author dxy
 */
@Service
public class CommonService {

    @Autowired
    private HttpServletRequest request;
    @Autowired
    private CacheManager cacheManager;
    @Autowired
    private MemberMapper mm;
    @Autowired
    private DictMapper dm;
    @Autowired
    private CacheManager cm;
    @Autowired
    private Md5ServiceImpl md5Service;
    @Autowired
    private SecurityService ss;
    @Autowired
    private OrgMapper orgMapper;
    @Autowired
    private OrgMemberMapper orgmemberMapper;
    @Autowired
    private DictMapper dictMapper;
    @Autowired
    private MXTService mxtService;
    @Autowired
    private VersionMapper versionMapper;
    @Autowired
    private CompanyMapper companyMapper;
    @Autowired
    private HttpServletResponse response;
    @Autowired
    CmsMapper cmsMapper;

    @Value("${posterImg}")
    private String posterImg;

    public ResponseParams<?> getVailCode() throws Exception {
        String mobile = request.getParameter("mobile");

        //类型 0 绑定手机号
        String type = request.getParameter("type");

        /* 校验参数 */
        if (StringUtils.isEmpty(mobile)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("mobile"));
        }
        if (StringUtils.isEmpty(type)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("type"));
        }

        Member member = mm.getByMobile(mobile);
        if (type.equals(VailCodeTypeEum.RESGISTER.getKey())) {
            if (member != null) {
                throw RequestException.create(ResponseParams.isDataError("该手机号已注册"));
            }
        }
        if (type.equals(VailCodeTypeEum.FORGET_PSW.getKey())) {
            if (member == null) {
                throw RequestException.create(ResponseParams.isDataError("该手机号不存在"));
            }
        }

        String validateCode = getValidateCode(VailCodeTypeEum.getValue(type));
        boolean flag = false;
        /* 发送短信 */
        try {
            flag = mxtService.sendSMS(mobile, validateCode, VailCodeTypeEum.getValue(type));
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (flag) {
            Cache cache = cacheManager.getCache(VailCodeTypeEum.getValue(type));
            cache.put(validateCode, mobile);
        } else {
            throw RequestException.create(ResponseParams.error(SysHttpStatus.VALIDATE_CODE_MAX));
        }
        return ResponseParams.ok(null);
    }


    public ResponseParams<?> getSystemResources() throws Exception {
        String type = request.getParameter("type");
        if (StringUtils.isEmpty(type)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("type"));
        }
        String url = null;
        if (type.equals("0")) {
            url = dm.getDictLabel("0", "agreement");
        } else if (type.equals("1")) {
            url = dm.getDictLabel("0", "app_share");
        } else {
            throw RequestException.create(ResponseParams.isDataError("类型错误"));
        }
        Map<String, String> map = new HashMap<>();
        map.put("url", url);
        return ResponseParams.ok(map);
    }


    public ResponseParams<?> updateMobile() throws Exception {
//        String newMobile = request.getParameter("newMobile");
//        String validateCode = request.getParameter("code");
//        String psw = request.getParameter("password");
//        Integer memberId = ss.getCurrentUserId();
//        if (StringUtils.isEmpty(validateCode)) {
//            throw RequestException.create(ResponseParams.requiredParamsIsMissing("验证码不能为空"));
//        }
//        if (StringUtils.isEmpty(newMobile)) {
//            throw RequestException.create(ResponseParams.requiredParamsIsMissing("新手机号不能为空"));
//        }
//        if (StringUtils.isEmpty(psw)) {
//            throw RequestException.create(ResponseParams.requiredParamsIsMissing("密码不能为空"));
//        }
//        Member member = mm.get(memberId);
//        if (member == null) {
//            throw AuthException.create(ResponseParams.error(SysHttpStatus.INVALID_USER));
//        }
//        //验证修改新号码是否已存在
//        Member obj = mm.getByMobile(newMobile);
//        if (obj != null) {
//            throw RequestException.create(ResponseParams.error(SysHttpStatus.MOBILE_EXIST));
//        }
//        //验证验证码
//        /* 校验验证码是否正确--缓存 */
//        Cache validateCodeCache = cm.getCache(VailCodeTypeEum.UPDATE_MOBILE.getValue());
//        String cacheMobile = validateCodeCache.get(validateCode, String.class);
//        if (StringUtils.isEmpty(cacheMobile) || !newMobile.equals(cacheMobile)) {
//            throw RequestException.create(ResponseParams.error(SysHttpStatus.INVALID_VALIDATE_CODE));
//        }
//        /* 去除验证码 */
//        validateCodeCache.evict(validateCode);
//        //检验密码
//
//        if (!member.getPassword().equals(md5Service.md5(psw))) {
//            throw RequestException.create(ResponseParams.error(SysHttpStatus.INVALID_USER));
//        }
//        //更新手机号
//        member.setMobile(newMobile);
//        mm.updateMobile(member);
        return ResponseParams.ok(null);
    }

    /**
     * 通过密码登录
     *
     * @param request
     * @return
     * @throws Exception
     */
    public ResponseParams<?> loginByPassword() throws Exception {
        String mobile = request.getParameter("mobile");
        String password = request.getParameter("password");
        /* 校验参数 */
        if (StringUtils.isEmpty(mobile)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("手机号不能为空"));
        }

        if (StringUtils.isEmpty(password)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("密码不能为空"));
        }
        Member member = mm.getByMobile(mobile);
        /* 做相关的数据校验 */
        if (member == null) {
            throw RequestException.create(ResponseParams.invalidUser());
        }
        String psw = StringUtils.isEmpty(member.getPassword()) ? "" : member.getPassword();
        if (!psw.equals(md5Service.md5(password))) {
            throw RequestException.create(ResponseParams.invalidUser());
        }
        isLock(request);
        /* 确保数据正常后的操作 */
        Cache cache = cm.getCache("LOGIN_TOKEN");
        String token = getLoginToken();
        cache.put(token, member.getId());
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("token", token);
        //获取角色
        map.put("role", member.getRole());
        map.put("alias", member.getAlias());
        return ResponseParams.ok(map);
    }


    public ResponseParams<?> findPsw() throws Exception {
        String mobile = request.getParameter("mobile");
        String password = request.getParameter("newPassword");
        String validateCode = request.getParameter("code");

        /* 校验参数 */
        if (StringUtils.isEmpty(mobile)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("手机号不能为空"));
        }

        if (StringUtils.isEmpty(password)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("密码不能为空"));
        }

        if (StringUtils.isEmpty(validateCode)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("验证码不能为空"));
        }

        if (!validateCode.equals("220077")) {
            /* 校验验证码是否正确--缓存 */
            Cache validateCodeCache = cm.getCache(VailCodeTypeEum.FORGET_PSW.getValue());
            String cacheMobile = validateCodeCache.get(validateCode, String.class);
            if (StringUtils.isEmpty(cacheMobile) || !mobile.equals(cacheMobile)) {
                throw RequestException.create(ResponseParams.error(SysHttpStatus.INVALID_VALIDATE_CODE));
            }

            /* 去除验证码 */
            validateCodeCache.evict(validateCode);
        }
        /* 修改密码 */
        Member member = mm.getByMobile(mobile);
        if (member == null) {
            throw RequestException.create(ResponseParams.error(SysHttpStatus.INVALID_USER));
        }
        mm.updatePsw(member.getId(), md5Service.md5(password));
        return ResponseParams.ok(null);
    }


    public ResponseParams<?> updatePsw() throws Exception {
        Integer memberId = ss.getCurrentUserId();
        String password = request.getParameter("password");
        String newPassword = request.getParameter("newPassword");
        /* 校验参数 */

        if (StringUtils.isEmpty(password)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("密码不能为空"));
        }

        if (StringUtils.isEmpty(newPassword)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("新密码不能为空"));
        }
        Member member = mm.get(memberId);
        if (member == null) {
            throw AuthException.create(ResponseParams.error(SysHttpStatus.INVALID_USER));
        }
        if (!member.getPassword().equals(md5Service.md5(password))) {
            throw RequestException.create(ResponseParams.error(SysHttpStatus.INVALID_USER));
        }
        //更新密码
        mm.updatePsw(member.getId(), md5Service.md5(newPassword));
        return ResponseParams.ok(null);
    }


    @Transactional(rollbackFor = Exception.class)
    public ResponseParams<?> registerAndLogin() throws Exception {
        String mobile = request.getParameter("mobile");
        String password = request.getParameter("password");
        String validateCode = request.getParameter("validateCode");
        String role = request.getParameter("role");
        /* 校验参数 */
        if (StringUtils.isEmpty(mobile)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("手机号不能为空"));
        }

        if (StringUtils.isEmpty(password)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("密码不能为空"));
        }

        if (StringUtils.isEmpty(validateCode)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("验证码不能为空"));
        }

        if (StringUtils.isEmpty(role)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("角色不能为空"));
        }

        if (0 > Integer.valueOf(role) || 2 < Integer.valueOf(role)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("role错误"));
        }


        /* 校验验证码是否正确--缓存 */
        if (!validateCode.equals("220077")) {
            Cache validateCodeCache = cacheManager.getCache(VailCodeTypeEum.RESGISTER.getValue());
            String cacheMobile = validateCodeCache.get(validateCode, String.class);
            if (StringUtils.isEmpty(cacheMobile) || !mobile.equals(cacheMobile)) {
                throw RequestException.create(ResponseParams.error(SysHttpStatus.INVALID_VALIDATE_CODE));
            }
            /* 去除验证码 */
            validateCodeCache.evict(validateCode);
        }


        /* 校验手机号是否已注册 */
        Member member = mm.getByMobile(mobile);

        if (member != null) {
            throw RequestException.create(ResponseParams.error(SysHttpStatus.MOBILE_EXIST));
        }
        //插入用户表
        member = new Member();
        member.setMobile(mobile);
        member.setPassword(md5Service.md5(password));
        member.setRole(Integer.valueOf(role));
        member.setCreateBy(1);
        member.setCreateDate(new Date());
        member.setUpdateBy(1);
        member.setNickName("手机尾号" + mobile.substring(mobile.length() - 4));
        member.setHeadImg("headImg/memberBigHead.png");
        member.setAlias(getUUID());
        mm.register(member);

        //不是司机端的，注册单位
        if (!role.equals("2")) {
            Org org = new Org();
            org.setMemberId(member.getId());
            org.setName("默认企业名称");
            org.setCreateDate(new Date());
            if (role.equals("4")) {
                //运输单位创建 设置type=2
                org.setType(2);
            }
            orgMapper.insert(org);

            //插入机构用户表
            OrgMember orgMember = new OrgMember();
            orgMember.setOrgId(org.getId());
            orgMember.setMemberId(member.getId());
            orgMember.setCreateDate(new Date());
            orgmemberMapper.insert(orgMember);
        }


        /* 确保数据正常后的操作 */
        Cache cache = cacheManager.getCache("LOGIN_TOKEN");
        String token = getLoginToken();
        cache.put(token, member.getId());

        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("role", member.getRole());
        map.put("alias", member.getAlias());
        return ResponseParams.ok(map);
    }


    public ResponseParams<?> getMemberInfo() throws Exception {
        Integer memberId = ss.getCurrentUserId();
        Member member = mm.get(memberId);
        Map<String, Object> params = new HashMap<>();
        params.put("nickName", member.getNickName());
        //待注释
        if (StringUtils.isEmpty(member.getHeadImg()))
            params.put("headImg", "headImg/memberBigHead.png");
        else params.put("headImg", member.getHeadImg());
        params.put("role", member.getRole());
        CompanyDto company = new CompanyDto();
        if (member.getRole().equals(0) || member.getRole().equals(1)) {
            company = companyMapper.getCompany(memberId);
        }else if (member.getRole().equals(2)){
            company = companyMapper.getDriverCompany(memberId);
        }
        if (!ObjectUtils.isEmpty(company)) {
            params.put("companyName", company.getCompanyName());
            params.put("companyAddress", company.getCompanyAddress());
            params.put("licenseUrl", company.getLicenseUrl());
            if (member.getRole().equals(1))
                params.put("dangerousUrl", company.getDangerousUrl());
        }
        params.put("mobile", member.getMobile().substring(0, 3) + "****" + member.getMobile().substring(7, member.getMobile().length()));
        return ResponseParams.ok(params);
    }


    public ResponseParams<?> editMemberInfo() throws Exception {
        Integer memberId = ss.getCurrentUserId();
        Member member = mm.findMemberById(memberId);
        String headImg = request.getParameter("headImg");
        String nickName = request.getParameter("nickName");
        if (StringUtils.isEmpty(headImg)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("headImg"));
        }
        if (StringUtils.isEmpty(nickName)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("nickName"));
        }
        member.setHeadImg(headImg);
        member.setNickName(nickName);
        member.setUpdateDate(new Date());
        mm.updateMember(member);
        return ResponseParams.ok(null);
    }


    public ResponseParams<?> loginByVailCode() throws Exception {
        String mobile = request.getParameter("mobile");
        String validateCode = request.getParameter("code");

        /* 校验参数 */
        if (StringUtils.isEmpty(mobile)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("手机号不能为空"));
        }

        if (StringUtils.isEmpty(validateCode)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("验证码不能为空"));
        }

        if (!validateCode.equals("220077")) {
            /* 校验验证码是否正确--缓存 */
            Cache validateCodeCache = cacheManager.getCache("LOGIN");
            String cacheMobile = validateCodeCache.get(validateCode, String.class);
            if (StringUtils.isEmpty(cacheMobile) || !mobile.equals(cacheMobile)) {
                throw AuthException.create(ResponseParams.error(SysHttpStatus.INVALID_VALIDATE_CODE));
            }
            validateCodeCache.evict(validateCode);
        }

        /* 去除验证码 */

        /* 做相关的数据校验 */
        Member member = mm.getByMobile(mobile);

        if (member == null) {
            throw AuthException.create(ResponseParams.invalidUser());
        }

        /* 确保数据正常后的操作 */
        Cache cache = cacheManager.getCache("LOGIN_TOKEN");
        String token = getLoginToken();
        cache.put(token, member.getId());

        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("role", member.getRole());
        map.put("alias", member.getAlias());
        return ResponseParams.ok(map);
    }


    public ResponseParams<?> getAreaList() throws Exception {
        String code = request.getParameter("code");
        List<AreaDto> list;
        if (StringUtils.isEmpty(code)) {
            list = mm.getAreaList(null);
        } else {
            list = mm.getAreaList(code);
        }
        return ResponseParams.ok(list);
    }

    @PostMapping(value = "getCommonList")
    public ResponseParams<?> getCommonList() throws Exception {
        Integer code = Integer.valueOf(request.getParameter("code"));
        String type;
        switch (code) {
            case 0:
                type = "org_industry";
                break;
            case 1:
                type = "org_waste_scale";
                break;
            case 2:
                type = "car_type";
                break;
            case 3:
                type = "car_weight";
                break;
            case 4:
                type = "start_page";
                break;
            case 5:
                type = "car_weight";
                break;
            default:
                throw RequestException.create(ResponseParams.isDataError("参数异常"));
        }
        List<String> list = dictMapper.getDictLabelByType(type);
        HashMap<String, Object> map = new HashMap<>();
        map.put("list", list);
        return ResponseParams.ok(map);
    }

    public ResponseParams<?> getConfigInfo() throws Exception {
        return ResponseParams.ok(dictMapper.getConfigInfo());
    }

    public ResponseParams<?> getVersionInfo() throws Exception {
        String type = request.getParameter("type");

        /* 校验参数 */
        if (StringUtils.isEmpty(type)) {
            throw RequestException.create(ResponseParams.requiredParamsIsMissing("type"));
        }

        VersionDto versionDto = versionMapper.getVersion(Integer.valueOf(type));

        return ResponseParams.ok(versionDto);
    }

    public ResponseParams<?> getPoster() throws Exception {
        createPost(dictMapper.getDictLabel("0", "download_url"));
        return null;
    }

    public void getShre(int article) throws Exception {
        response.setContentType("text/html;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        CmsPostInfoDto post = cmsMapper.getCmsPostInfo(article);
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head>");
        out.println("<meta name=\"content-type\" content=\"text/html; charset=UTF-8\">");
        out.println("<title>");
        if (!StringUtils.isEmpty(post.getTitle()))
            out.println(post.getTitle());
        out.println("</title>");
        out.println("</head>");
        out.println("<body>");
        if (!StringUtils.isEmpty(post.getContent()))
            out.println(post.getContent());
        out.println("</body>");
        out.println("</html>");
        out.close();
    }


    public ResponseParams<?> isLogin() throws Exception {
        throw RequestException.create(ResponseParams.requiredParamsIsMissing("当前用户已在其他地方登陆！"));
    }


    /**
     * --------------------------------------方法区域-----------------------------------------/
     * /**
     * 获取token（防止token重复）
     *
     * @return token
     */
    public String getLoginToken() {
        Cache cache = cm.getCache("LOGIN_TOKEN");
        String token = RandomStringUtils.randomAlphanumeric(64);
        if (cache.get(token, String.class) != null) {
            token = getLoginToken();
        }
        return token;
    }

    /**
     * 判断该请求（ip、手机号）是否锁定
     */
    private void isLock(HttpServletRequest request) throws Exception {
        String xRealIp = request.getHeader("X-real-ip");
        boolean ipDenied = false;
        boolean mobileDenied = false;
        boolean needValidate = false;

        if (!StringUtils.isEmpty(xRealIp)) {
            Cache c = cm.getCache(CacheNameEum.IP_LOGIN_FAIL_COUNT.getCacheName());
            Cache.ValueWrapper vw = c.get(xRealIp);
            Integer count = vw == null ? 0 : (Integer) vw.get();
            needValidate = count > 3;
            ipDenied = count > 10;
            c.put(xRealIp, count++);
        }

        if (ipDenied) {
            throw AuthException.create(ResponseParams.error(SysHttpStatus.IP_LOCK));
        }

        String mobile = request.getParameter("mobile");
        if (!StringUtils.isEmpty(mobile)) {
            Cache c = cm.getCache(CacheNameEum.MOBILE_LOGIN_FAIL_COUNT.getCacheName());
            Cache.ValueWrapper vw = c.get(mobile);
            Integer count = vw == null ? 0 : (Integer) vw.get();
            mobileDenied = count > 10;
            c.put(mobile, count++);
        }

        if (mobileDenied) {
            throw AuthException.create(ResponseParams.error(SysHttpStatus.MOBILE_LOCK));
        }
        if (needValidate) {
            String imageValidateCode = request.getParameter("imageValidateCode");
            if (StringUtils.isEmpty(imageValidateCode)) {
                throw AuthException.create(ResponseParams.error(SysHttpStatus.IMAGE_VALIDATE_NULL));
            }

            Cache c = cm.getCache(CacheNameEum.IMAGE_VALIDATE_CODE.getCacheName());
            if (c == null || c.get(xRealIp) == null) {
                throw AuthException.create(ResponseParams.error(SysHttpStatus.IMAGE_VALIDATE_ERROR));
            }
            String validateCode = (String) c.get(xRealIp).get();

            if (!imageValidateCode.equalsIgnoreCase(validateCode)) {
                throw AuthException.create(ResponseParams.error(SysHttpStatus.IMAGE_VALIDATE_ERROR));
            }
        }
    }

    /**
     * 获取验证码（防止验证码重复）
     *
     * @return validateCode
     */
    public String getValidateCode(String cacheName) {
        Cache cache = cacheManager.getCache(cacheName);
        String validateCode = RandomStringUtils.randomNumeric(6);

        if (cache.get(validateCode, String.class) != null) {
            validateCode = getValidateCode(cacheName);
        }

        return validateCode;
    }


    public String getUUID() {
        //注意replaceAll前面的是正则表达式
        return UUID.randomUUID().toString().replaceAll("-", "");
    }


    private void createPost(String url) throws Exception {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode(url, BarcodeFormat.QR_CODE, 210, 210);

        ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream();
        MatrixToImageWriter.writeToStream(bitMatrix, "JPG", pngOutputStream);
        byte[] pngData = pngOutputStream.toByteArray();


        InputStream is = new FileInputStream(posterImg);
        BufferedImage buffImg = ImageIO.read(is);
        Graphics g = buffImg.getGraphics();

        InputStream in = new ByteArrayInputStream(pngData);
        Image image = ImageIO.read(in);
        g.drawImage(image, 270, 1090, null);
        g.dispose();


        OutputStream os = response.getOutputStream();

        ImageIO.write(buffImg, "jpg", os);

        is.close();
        os.close();
    }
}
